package com.ldn.server.manage.controller;

import cn.dev33.satoken.annotation.SaCheckLogin;
import com.ldn.common.basic.dispose.bo.FileInfoBo;
import com.ldn.common.basic.dispose.dto.UploadDto;
import com.ldn.common.basic.dispose.exception.AppException;
import com.ldn.common.basic.dispose.vo.UploadVo;
import com.ldn.common.basic.utils.system.DataUtils;
import com.ldn.server.manage.config.annotation.ServerManageController;
import lombok.extern.slf4j.Slf4j;
import net.coobird.thumbnailator.Thumbnails;
import org.springframework.util.ClassUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.util.Objects;

/**
 * 文件上传相关接口
 *
 * @author 李大牛家的牛 (scafel@163.com)
 * @product serverless
 * @className UploadController
 * @createDate 2025/2/18 - 14:09
 * @description 文件上传
 **/
@Slf4j
@RestController
@ServerManageController("upload")
public class UploadController {


    /**
     * showdoc 图片上传接口
     * @catalog 总后台接口/文件上传
     * @title 图片上传接口
     * @description 图片上传接口
     * @method POST
     * @url _url/api/manage/upload/image
     * @header authorization 必选 用户登录token
     * @param dto 必选 {@link UploadDto} 文件上传参数
     * @return vo {@link UploadVo} 文件上传返回值
     * @remark 无
     */
    @SaCheckLogin
    @PostMapping("/image")
    public UploadVo uploadImage(UploadDto dto) {
        // 当前使用本地上传，后续可以使用阿里、百度、腾讯等第三方服务
        return uploadDisk(dto);
    }

    /**
     * 本地文件上传到代码服务器
     *  <p>
     *      1. 需要验证是否有服务器url
     *      2. 验证是否需要压缩图片
     *  </p>
     * @param dto {@link UploadDto} 文件上传参数
     * @return {@link UploadVo} 文件上传返回值
     */
    private UploadVo uploadDisk(UploadDto dto) {
        // 获取文件访问路径
        String yccurl = "";
        // 是否压缩图片
        boolean sfystp = false;
        try {
            FileInfoBo bo = getFileInfo(dto);
            File localFile = uploadFile(dto, bo);
            if (sfystp && isImage(bo.getFileSuffix())){
                File thumbnailsTempFile = File.createTempFile("thumbnails-" + bo.getFileName(), bo.getFileSuffix(), new File(bo.getFileDir()));
                Thumbnails.of(localFile).scale(0.5f).outputQuality(0.5f).toFile(thumbnailsTempFile);
                Files.move(thumbnailsTempFile.toPath(), thumbnailsTempFile.toPath().resolveSibling("thumbnails-" + bo.getFileName() + bo.getFileSuffix()));
                localFile = new File(bo.getFileDir()  + "/thumbnails-" + bo.getFileName() + bo.getFileSuffix() );
            }
            UploadVo vo = new UploadVo();
            vo.setFileName(localFile.getName());
            vo.setFilePath(bo.getFileDir());
            vo.setFileUrl(yccurl + "/" + bo.getFolderName() +"/"+vo.getFileName());
            return vo;
        } catch (Exception e) {
            log.error("文件保存失败 ", e);
            throw new AppException("文件保存失败");
        }
    }

    public static File uploadFile(UploadDto dto, FileInfoBo bo) throws IOException {
        MultipartFile file = (MultipartFile) dto.getFile();
        File localFile = File.createTempFile(bo.getFileDir(), bo.getFileSuffix(), new File(bo.getFileDir()));
        file.transferTo(localFile);
        if (!localFile.exists()){
            log.error("文件保存失败 ex =>{}", localFile);
        }
        Files.move(localFile.toPath(), localFile.toPath().resolveSibling(bo.getFileName() + bo.getFileSuffix()));
        return new File(bo.getFileDir() + "/" + bo.getFileName() + bo.getFileSuffix() );
    }

    /**
     * 获取文件基本信息
     *
     * @param dto
     * @return
     */
    public static FileInfoBo getFileInfo(UploadDto dto) {
        FileInfoBo bo = new FileInfoBo();
        MultipartFile file = (MultipartFile) dto.getFile();
        String fileName = file.getOriginalFilename();
        if (fileName == null ||fileName.isBlank()){
            throw new AppException("文件名不能为空");
        }
        String suffix = fileName.substring(fileName.lastIndexOf("."));
        bo.setFileSuffix(suffix);
        String name = DataUtils.getCode(dto.getPrefix());
        bo.setFileName(name);
        String path = Objects.requireNonNull(Objects.requireNonNull(ClassUtils.getDefaultClassLoader()).getResource("")).getPath();
        File classDir = new File(path);
        File staticDir = new File(classDir.getParent());
        String folderName = dto.getGroup() + "/" + dto.getPrefix();
        // 存储到服务的路径
        bo.setFileDir(staticDir.getParent() + "/static/"  + folderName);
        bo.setFolderName(folderName);
        File dir = new File(bo.getFileDir());
        if (!dir.exists()){
            if (!dir.mkdirs()){
                throw new AppException("目录创建失败");
            }
        }
        return bo;
    }

    public static boolean isImage(String extension) {
        String[] imageExtension = new String[]{".jpeg", ".jpg", ".gif", ".bmp", ".png"};
        for (String e : imageExtension) {
            if (extension.toLowerCase().equals(e)) {
                return true;
            }
        }
        return false;
    }
}
